package sequencing;

import anim.AnimationClips;
import dae.Animation;
import dae.Collada;
import dae.library.VisualScene;
import util.JAXBUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;

public class DaeInfoManager
{
    //    public Map <String, AnimFragments> boneAnimFragments = new TreeMap <>();
    //    public Map <String, GameObject> boneSourceNode = new TreeMap <>();

    public Map<String, BoneInfo> boneInfoMap = new TreeMap<>();
    private Collada collada;

    public TreeSet<BoneInfo> nodesToSet()
    {
        TreeSet<BoneInfo> gameObjects = new TreeSet<>();
        gameObjects.addAll(boneInfoMap.values());
        return gameObjects;
    }

    public DaeInfoManager(String path)
    {
        collada = null;
        try
        {
            collada = JAXBUtil.parseXmlFromFile(path, Collada.class, "default");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        if (collada == null)
        {
            return;
        }
        List<AnimationClips> clipsList = new ArrayList<>();
        if (collada.library_animations != null)
        {
            for (Animation animData : collada.library_animations.animation)
            {
                AnimationClips clips = new AnimationClips(animData);
                clipsList.add(clips);
            }
        }
        addAllAnimInfo(clipsList);
        List<GameObject> sceneObjects = new ArrayList<>();
        for (VisualScene visual_scene : collada.library_visual_scenes.visual_scene)
        {
            GameObject sceneObject = new GameObject(visual_scene);
            sceneObjects.add(sceneObject);
        }
        addAllBoneInfo(sceneObjects);
        initBoneRootMatrix();
    }

    private void initBoneRootMatrix()
    {
        for (String boneName : boneInfoMap.keySet())
        {
            BoneInfo info = boneInfoMap.get(boneName);
            if (info.animFragments != null)
            {
                int frames = info.animFragments.inputs.size();
                for (int i = 0; i < frames; i++)
                {
                    int frameIndex=Math.round( info.animFragments.inputs.get(i)/0.03333f);
                    AnimController.calculateTransformForOneBone(this, frameIndex, boneName);
                }
            }
        }
    }

    private void addAllAnimInfo(List<AnimationClips> clipsList)
    {
        if (clipsList == null)
        {
            return;
        }
        for (AnimationClips animationClips : clipsList)
        {
            animationClips.allAnimMap.forEach((key, value) ->
            {
                BoneInfo boneInfo = new BoneInfo();
                BoneInfo existed = boneInfoMap.getOrDefault(key, boneInfo);
                existed.animFragments = value;
                boneInfoMap.put(key, existed);
            });
        }
    }

    private void addAllBoneInfo(List<GameObject> sceneObjects)
    {
        if (sceneObjects == null)
        {
            return;
        }
        for (GameObject gameObject : sceneObjects)
        {
            BoneInfo boneInfo = new BoneInfo();
            if (gameObject.name == null)
            {
                continue;
            }
            BoneInfo existed = boneInfoMap.getOrDefault(gameObject.name, boneInfo);
            existed.object = gameObject;
            boneInfoMap.put(gameObject.name, existed);
            addAllBoneInfo(gameObject.children);
        }
    }
}
